package org.dtrd.modules.content.tags.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.dtrd.common.exception.JeecgBootException;
import org.dtrd.modules.content.tags.entity.bean.TagDetail;
import org.dtrd.modules.content.tags.entity.po.DtrdEntRdTag;
import org.dtrd.modules.patient.entity.po.DtrdRlPatientTag;
import org.dtrd.modules.content.tags.mapper.DtrdEntRdTagMapper;
import org.dtrd.modules.content.tags.service.IDtrdEntRdTagService;
import org.dtrd.modules.patient.service.IDtrdRlPatientTagService;
import org.dtrd.common.util.StringUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;


/**
 * <p>
 * 标签表 服务实现类
 * </p>
 *
 * @author QR
 * @since 2022-03-08
 */
@DS("multi-datasource1")
@Service
public class DtrdEntRdTagServiceImpl extends ServiceImpl<DtrdEntRdTagMapper, DtrdEntRdTag> implements IDtrdEntRdTagService {

    @Autowired
    private IDtrdRlPatientTagService patientTagRlService;

    @Override
    public List<Integer> getPatientIdByTags(List<Integer> tagIds) {
        return baseMapper.selectPatientIdByTags(tagIds, tagIds.size());
    }

    @Override
    public TagDetail getTag(Integer dataId) {
        DtrdEntRdTag dtrdEntRdTag = getById(dataId);
        return Optional.ofNullable(dtrdEntRdTag)
                        .map(po -> new TagDetail().parseFromPO(po))
                        .orElse(null);
    }

    @Override
    public Map<String, Integer> getTagName2Id() {
        List<DtrdEntRdTag> list = list();
        Map<String, Integer> map = new HashMap<>();
        for (DtrdEntRdTag tag : list) {
            map.put(tag.getTagName(), tag.getDataId());
        }
        return map;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean savePatientTag(Integer patientId, List<TagDetail> tags) {
        Map<String, Integer> tagName2Id = getTagName2Id();
        // 需要新增关系表tagIds
        List<Integer> newPatientTagIds = new ArrayList<>(tags.size());
        // 需要处理的 tag 转换成 po
        List<DtrdEntRdTag> poList = tags.stream()
                .map(tag -> new DtrdEntRdTag().parseFromDTO(tag))
                .collect(Collectors.toList());
        // 去除不需要新生成的 tag
        if (CollectionUtil.isNotEmpty(poList)) {
            Iterator<DtrdEntRdTag> tagIterator = poList.iterator();
            while (tagIterator.hasNext()) {
                DtrdEntRdTag tag = tagIterator.next();
                Integer tagId = tagName2Id.get(tag.getTagName());
                if (tagId != null) {
                    newPatientTagIds.add(tagId);
                    tagIterator.remove();
                }
            }
        }
        // 保存新增的 tag
        if (CollectionUtil.isNotEmpty(poList)) {
            saveBatch(poList);
            // 获取新增的 tagId
            poList.forEach(po -> newPatientTagIds.add(po.getDataId()));
        }
        // 保存 tag&patient
        if (CollectionUtil.isNotEmpty(newPatientTagIds)) {
            for (Integer patientTagId : newPatientTagIds) {
                LambdaQueryWrapper<DtrdRlPatientTag> wrapper = Wrappers.lambdaQuery(DtrdRlPatientTag.class)
                        .eq(DtrdRlPatientTag::getTagId, patientTagId)
                        .eq(DtrdRlPatientTag::getPatientId, patientId);
                DtrdRlPatientTag patientTag = new DtrdRlPatientTag(patientId, patientTagId);
                boolean result = patientTagRlService.saveOrUpdate(patientTag, wrapper);
                if (!result) {
                    throw new JeecgBootException("修改患者标签失败");
                }
            }
        }
        return true;
    }

    @Override
    public boolean saveOrUpdateTag(TagDetail dto) {
        DtrdEntRdTag dtrdEntRdTag = new DtrdEntRdTag();
        if(dto.getTagId() == null){
            dtrdEntRdTag = dtrdEntRdTag.init();
        }
        dtrdEntRdTag.parseFromDTO(dto);
        return saveOrUpdate(dtrdEntRdTag);
    }

    @Override
    public boolean removeTag(Integer dataId) {
        return removeById(dataId);
    }

    @Override
    public List<TagDetail> listTags(String tagName) {
        LambdaQueryWrapper<DtrdEntRdTag> wrapper = baseQueryWrapper();
        if (StrUtil.isNotBlank(tagName)) {
            wrapper.like(DtrdEntRdTag::getTagName, StringUtil.fuzzySearchWrapper(tagName));
        }
        return listTags(wrapper);
    }

    private List<TagDetail> listTags(LambdaQueryWrapper<DtrdEntRdTag> wrapper){
        List<DtrdEntRdTag> list = list(wrapper);
        return Optional.ofNullable(list)
                .map(l -> l.stream().map(po -> new TagDetail().parseFromPO(po)).collect(Collectors.toList()))
                .orElse(null);
    }

    private LambdaQueryWrapper<DtrdEntRdTag> baseQueryWrapper() {
        return Wrappers.lambdaQuery(DtrdEntRdTag.class)
                        .eq(DtrdEntRdTag::getIsDel, 0);
    }

    private LambdaUpdateWrapper<DtrdEntRdTag> baseUpdateWrapper() {
        return Wrappers.lambdaUpdate(DtrdEntRdTag.class)
                        .eq(DtrdEntRdTag::getIsDel, 0);
    }
}
